package dbobj

import (
	//"encoding/json"

	"fmt"
	"time"

	"github.com/aidarkhanov/nanoid/v2"

	"iot-base/common/dbconn"

	"iot-base/common/idsync"
	"iot-base/common/logger"
	"iot-base/common/notify"

	"gorm.io/datatypes"
	"gorm.io/gorm"
)

//Thing 事务
type Thing struct {
	UID          string  `gorm:"type:varchar(40);primaryKey;not null;" json:"uid" redis:"UID" mapstructure:"uid"`
	SName        string  `gorm:"type:varchar(100);not null" json:"s_name" redis:"SName" mapstructure:"uid"`
	ModelID      string  `gorm:"type:varchar(40);not null" json:"model_id" redis:"ModelID" mapstructure:"model_id"` //模型id
	TModelPtr    *TModel `gorm:"foreignKey:ModelID" json:"-" mapstructure:"-"`
	IsProxy      bool    `json:"is_proxy"   redis:"IsProxy" mapstructure:"is_proxy"`                                   //是否为代理，如果是代理，相当于网关 true：该设备可通过网络上报数据，也可以帮助其他设备上报数据；
	IsStation    bool    `json:"is_station"  redis:"IsStation" mapstructure:"is_station"`                              //
	StatusUsed   int     `gorm:"not null;default:-2" json:"status_used" redis:"StatusUsed" mapstructure:"status_used"` //使用状态，施工中 -1 ，启用 1 停用 0
	ProtocolPath string  `json:"protocol_path"  redis:"ProtocolPath" mapstructure:"protocol_path"`
	Level        int64   `gorm:"default:2" redis:"Level" json:"level" mapstructure:"level"`
	ProxyThingID string  `gorm:"not null;default:''" json:"proxy_thing_id" redis:"ProxyThingID" mapstructure:"proxy_thing_id"` //代理的id
	BusinessID   string  `gorm:"type:varchar(100);" json:"business_id" redis:"BusinessID" mapstructure:"businessID"`
	Lon          string  `gorm:"type:varchar(20)" json:"lon" redis:"Lon" mapstructure:"Lon"`
	Lat          string  `gorm:"type:varchar(20)" json:"lat" redis:"Lat" mapstructure:"Lat"`
	//false 该设备不能通过网络上报数据

	//Rule    datatypes.JSON `json:"rule"` //规则
}

//ThingMaintainInfo 设备运维信息
type ThingMaintainInfo struct {
	ThingID         string     `gorm:"type:varchar(40);primaryKey;not null;" json:"thing_id"`
	BuyTime         *time.Time `gorm:"column:buy_time" json:"buy_time"`
	CreateTime      *time.Time `json:"create_time"`
	UsedTime        *time.Time `json:"used_time"`
	Maintain        string     `json:"maintain"`
	Creator         string     `json:"creator"`
	FirstOnlineTime *time.Time `gorm:"column:first_online_time" json:"first_online_time"`
}

//SetName 设置名称
func (pObj *Thing) SetName(name string) {
	pObj.SName = name
}

//GetID 获取id
func (pObj *Thing) GetID() interface{} {
	return pObj.UID
}

//GetName 获取名称
func (pObj *Thing) GetName() string {
	return pObj.SName
}

//AutoID 自动生成id
func (pObj *Thing) AutoID() {
	v, _ := nanoid.New()
	pObj.UID = fmt.Sprintf("%v", v)
}

//ThingParam 物参数
type ThingParam struct {
	dbconn.OBJObjIID
	ThingID    string `gorm:"type:varchar(40);uniqueIndex:thing_param_index" json:"thing_id"` //`gorm:"comment '物id'"`              //物id
	ThingPtr   *Thing `gorm:"foreignKey:ThingID" json:"-"`
	ParamID    string `gorm:"type:varchar(40);uniqueIndex:thing_param_index" json:"param_id"`
	ParamValue string `json:"param_value"`
	//DefaultValue string `json:"default_value"`
}

//Area 行政区域
type Area struct {
	//InitAPI
	SName     string `gorm:"type:varchar(100);index"json:"s_name"`
	UID       string `gorm:"primarykey;type:varchar(100);"json:"uid"`
	ParentID  string `gorm:"type:varchar(100);index:p_index;not null" json:"parent_id"`
	Level     string `gorm:"type:varchar(100);default:''"json:"level"`
	WholeName string `gorm:"type:varchar(300);uniqueIndex:w_name" json:"whole_name"`
	Lon       string `gorm:"type:varchar(20)" json:"lon" redis:"Lon" mapstructure:"Lon"`
	Lat       string `gorm:"type:varchar(20)" json:"lat" redis:"Lat" mapstructure:"Lat"`
	CityCode  string `gorm:"type:varchar(10);not null;default:''" json:"city_code""`
	ZipCode   string `gorm:"type:varchar(6);not null;default:''" json:"zip_code"`
	Adcode    string `gorm:"type:varchar(10);not null;default:''" json:"adcode"`
	PinYin    string `gorm:"type:varchar(400);not null;default:''" json:"pin_yin"`
	SimplePy  string `gorm:"type:varchar(200);not null;default:''" json:"pin_yin"`
	PerPinYin string `gorm:"type:char(1);not null;default:''" json:"per_pin_yin"`
	Path      string `gorm:"type:varchar(400);default:''" json:"path"`
	//SName string `gorm:"type:varchar(100);not null" json:"s_name"`
}

//GetID 获取id
func (pObj *Area) GetID() interface{} {
	return pObj.UID
}

//GetName 获取名称
func (pObj *Area) GetName() string {
	return pObj.SName
}

//AutoID 自动生成id
func (pObj *Area) AutoID() {
}

//Station 场站
type Station struct {
	dbconn.DBObjIDName
	Lon    string `gorm:"type:varchar(20)" json:"lon" redis:"Lon" mapstructure:"Lon"`
	Lat    string `gorm:"type:varchar(20)" json:"lat" redis:"Lat" mapstructure:"Lat"`
	Desc   string `gorm:"type:varchar(200);" json:"desc"`
	Level  int    `json:"level"`
	AreaID string `gorm:"not null" json:"area_id"`
	//AreaPtr  *Area          `gorm:"foreignKey:AreaID"  json:"-"`
	Rule     datatypes.JSON `json:"rule"`
	ParentID string         `gorm:"type:varchar(40);" json:"parent_id"`
}

//ThingState 设备状态
type ThingState struct {
	ThingID     string    `gorm:"type:varchar(200);primaryKey;" json:"thing_id"`
	State       int       `json:"state"`
	ChangedTime time.Time `json:"change_time"`
}

//ThingStation 场站关系
type ThingStation struct {
	//IID       int    `gorm:"primary_key;AUTO_INCREMENT"` //主键
	ThingID   string `gorm:"type:varchar(40);primaryKey" json:"thing_id"` //`gorm:"comment '物id'"`              //物id
	Thing     Thing  `gorm:"foreignKey:ThingID"`
	StationID string `gorm:"type:varchar(40);uniqueIndex:t_station_no_index" json:"station_id"` //`gorm:"comment '场站id'"`
	ModelID   string `gorm:"type:varchar(40);uniqueIndex:t_station_no_index" json:"model_id"`
	//Station   Station `gorm:"foreignKey:StationID"  json:"-"`
	SNO int `gorm:"uniqueIndex:t_station_no_index" json:"sno"`
	//BusinessID string   `gorm:"type:varchar(40)" json:"business_id"` //`gorm:"comment '行业id'"` //行业id
	//Business   Business `gorm:"foreignKey:BusinessID"`
}

//GetID 获取id
func (st *ThingStation) GetID() interface{} {
	return st.ThingID
}

//AutoID 设置id
func (st *ThingStation) AutoID() {
}
func (ts *ThingStation) AfterDelete(tx *gorm.DB) (err error) {
	idsync.DirtyStationChildren(ts.StationID)
	return nil
}
func (ts *ThingStation) AfterSave(tx *gorm.DB) (err error) {
	idsync.DirtyStationChildren(ts.StationID)
	return nil
}

//BeforeDelete 在同一个事务中更新数据
func (t *Thing) BeforeDelete(tx *gorm.DB) (err error) {
	if t != nil {
		//var ts ThingStation
		//ts.ThingID = t.UID
		//tx.Unscoped().Delete(&ts)
		//var st ThingStation
		err = tx.Exec("delete from thing_params where thing_id=?", t.UID).Error
		if err != nil {
			return err
		}
		err := tx.Exec("delete from thing_stations where thing_id=?", t.UID).Error
		if err != nil {
			return err
		}
		err = tx.Exec("delete from thing_stations where station_id=?", t.UID).Error
		if err != nil {
			return err
		}
		err = tx.Exec("delete from stations where uid=?", t.UID).Error
		if err != nil {
			return err
		}
		//tx.Exec("delete from alarm_historys where t_id=?", t.UID)
		err = tx.Exec("delete from alarm_states where t_id=?", t.UID).Error
		if err != nil {
			return err
		}
		err = tx.Exec("delete from video_relations where t_id=?", t.UID).Error
		if err != nil {
			return err
		}
		err = tx.Exec("delete from thing_maintain_infos where thing_id=?", t.UID).Error
		if err != nil {
			return err

		}
		err = tx.Exec("delete from thing_alarm_rules where thing_id=?", t.UID).Error
		if err != nil {
			return err
		}

		tx.Exec("delete from alarm_shields where target_id=? and target_type = 'thing'",
			t.UID)

		tx.Exec("delete from dev_pick_templates where thing_id =?", t.UID)
		return err
		/*err = tx.Exec("delete from thing_rules where thing_id=?", t.UID).Error
		if err != nil {
			return err
		}*/

	}
	return nil
}
func (t *Thing) BeforeCreate(tx *gorm.DB) (err error) {
	if t.UID == "" {
		t.AutoID()
	}
	logger.SLog.Info("--------------before create-----------", t)
	idsync.AddThing(t.UID)
	return nil

}

func notifyDirty(id string) {
	logger.SLog.Info("--------------notify----beforesleep-------", id)
	time.Sleep(time.Duration(300) * time.Millisecond)
	idsync.DirtyThing(id)
	logger.SLog.Info("--------------notify-----------", id)
}

//AfterUpdate 更新后更新redis
func (t *Thing) AfterSave(tx *gorm.DB) (err error) {
	go notifyDirty(t.UID)
	return nil
}

//AfterDelete 删除后更新redis
func (t *Thing) AfterDelete(tx *gorm.DB) (err error) {
	idsync.RemoveThingID(t.UID)
	fmt.Println("&&&&&&&&&&&&&&&&&&&&&&&&&removeobj-------------", t.UID)
	notify.PubMsg(true, "objRemoved", t.UID)

	return idsync.DirtyThing(t.UID)
}

//AfterDelete 删除后更新redis
func (m *TModel) AfterDelete(tx *gorm.DB) (err error) {
	return idsync.DirtyTModel(m.UID)
}

//AfterUpdate 更新后更新redis
func (m *TModel) AfterSave(tx *gorm.DB) (err error) {
	fmt.Println("-----------------dirty model----------", m.UID)
	return idsync.DirtyTModel(m.UID)
}

/*
//ThingConnection 连接关系
type ThingConnection struct {
	//UID int `gorm:"primary_key;AUTO_INCREMENT"`
	//dbconn.OBJObjIID        //主键
	dbconn.OBJObjIID
	ThingID  string         `gorm:"type:varchar(40);uniqueIndex:t_type_index" json:"thing_id"` //`gorm:"comment '物id'"`              //物id
	Thing    Thing          `gorm:"foreignKey:ThingID"  json:"-"`
	ParentID string         `gorm:"type:varchar(40)" json:"parent_id"`
	Parent   Thing          `gorm:"foreignKey:ParentID"  json:"-"`                           //`gorm:"comment '父节点id'"`            //父节点id
	Ctype    string         `gorm:"type:varchar(40);uniqueIndex:t_type_index" json:"ctype"` //`gorm:comment '连接类型'"`
	Param    datatypes.JSON `json:"param"`
	//连接类型
}*/

func init() {

	/*dbconn.DBConnection.Model(&TModel{}).AddForeignKey("catalog_id", "t_catalog(uid)", "RESTRICT", "RESTRICT")
	dbconn.DBConnection.Model(&Catalog{}).AddForeignKey("business_id", "t_business(uid)", "RESTRICT", "RESTRICT")
	dbconn.DBConnection.Model(&Thing{}).AddForeignKey("model_id", "t_t_model(uid)", "RESTRICT", "RESTRICT")
	dbconn.DBConnection.Model(&Station{}).AddForeignKey("business_id", "t_business(uid)", "RESTRICT", "RESTRICT")
	dbconn.DBConnection.Model(&Station{}).AddForeignKey("uid", "t_thing(uid)", "RESTRICT", "RESTRICT")
	dbconn.DBConnection.Model(&ThingConnection{}).AddForeignKey("thing_id", "t_thing(uid)", "RESTRICT", "RESTRICT")
	dbconn.DBConnection.Model(&ThingConnection{}).AddForeignKey("parent_id", "t_thing(uid)", "RESTRICT", "RESTRICT")
	dbconn.DBConnection.Model(&ThingStation{}).AddForeignKey("thing_id", "t_thing(uid)", "RESTRICT", "RESTRICT")
	dbconn.DBConnection.Model(&ThingStation{}).AddForeignKey("station_id", "t_thing(uid)", "RESTRICT", "RESTRICT")*/

}
